home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / faxcover / faxcover.c++ next >
C/C++ Source or Header  |  1994-08-01  |  10KB  |  375 lines

  1. /*    $Header: /usr/people/sam/fax/faxcover/RCS/faxcover.c++,v 1.29 1994/02/28 14:13:25 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. #include "StrArray.h"
  26. #include "FaxDB.h"
  27. #include "config.h"
  28. #include "PageSize.h"
  29.  
  30. #include <stdarg.h>
  31. #include <ctype.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <time.h>
  35. #include <osfcn.h>
  36. #include <pwd.h>
  37. #include <fcntl.h>
  38. #include <sys/file.h>
  39. #include <stdlib.h>
  40.  
  41. class faxCoverApp {
  42. private:
  43.     fxStr    appName;    // for error messages
  44.     fxStr    cover;        // prototype cover sheet
  45.     FaxDB*    db;        // fax machine database
  46.     fxStr    toName;        // to person's name
  47.     fxStr    toFaxNumber;    // to's fax number
  48.     fxStr    toVoiceNumber;    // to's voice number
  49.     fxStr    toLocation;    // to's geographical location
  50.     fxStr    toCompany;    // to's company/institution
  51.     fxStr    regarding;    // fax is regarding...
  52.     fxStr    comments;    // general comments
  53.     fxStr    sender;        // sender's identity
  54.     fxStr    pageCount;    // # pages, not counting cover page
  55.     float    pageWidth;    // page width (mm)
  56.     float    pageLength;    // page length (mm)
  57.  
  58.     static fxStr dbName;
  59.  
  60.     fxStr tildeExpand(const fxStr& filename);
  61.     void setupPageSize(const char* name);
  62.     void emitToDefs(const char* to, FaxDBRecord* rec);
  63.     void emitFromDefs(FaxDBRecord* rec);
  64.     void emitCommentDefs();
  65.     void emitDateDefs();
  66.     void coverDef(const char* tag, const char* value);
  67.     void makeCoverSheet();
  68.     void usage();
  69.     void printError(const char* va_alist ...);
  70. public:
  71.     faxCoverApp();
  72.     ~faxCoverApp();
  73.  
  74.     void initialize(int argc, char** argv);
  75.     void open();
  76. };
  77.  
  78. fxStr faxCoverApp::dbName("~/.faxdb");
  79.  
  80. faxCoverApp::faxCoverApp() : cover(FAX_COVER)
  81. {
  82.     db = 0;
  83. }
  84.  
  85. faxCoverApp::~faxCoverApp()
  86. {
  87. }
  88.  
  89. void
  90. faxCoverApp::initialize(int argc, char** argv)
  91. {
  92.     extern int optind;
  93.     extern char* optarg;
  94.     int c;
  95.  
  96.     appName = argv[0];
  97.     u_int l = appName.length();
  98.     appName = appName.tokenR(l, '/');
  99.  
  100.     const char* cp = getenv("FAXCOVER");
  101.     if (cp && *cp)
  102.     cover = cp;
  103.  
  104.     setupPageSize("default");
  105.     while ((c = getopt(argc, argv, "C:n:t:f:c:p:l:r:s:v:x:")) != -1)
  106.     switch (c) {
  107.     case 's':            // page size
  108.         setupPageSize(optarg);
  109.         break;
  110.     case 'C':            // cover sheet
  111.         cover = optarg;
  112.         break;
  113.     case 'n':            // fax number
  114.         toFaxNumber = optarg;
  115.         break;
  116.     case 'r':            // regarding
  117.         regarding = optarg;
  118.         break;
  119.     case 't':            // to identity
  120.         toName = optarg;
  121.         break;
  122.     case 'f':            // from identity
  123.         sender = optarg;
  124.         break;
  125.     case 'c':            // comments
  126.         comments = optarg;
  127.         break;
  128.     case 'p':            // page count
  129.         pageCount = optarg;
  130.         break;
  131.     case 'l':            // to's location
  132.         toLocation = optarg;
  133.         break;
  134.     case 'v':            // to's voice phone number
  135.         toVoiceNumber = optarg;
  136.         break;
  137.     case 'x':            // to's company
  138.         toCompany = optarg;
  139.         break;
  140.     case '?':
  141.         usage();
  142.     }
  143.     if (sender == "" || toFaxNumber == "")
  144.     usage();
  145. }
  146.  
  147. extern void fxFatal(const char* fmt, ...);
  148.  
  149. void
  150. faxCoverApp::setupPageSize(const char* name)
  151. {
  152.     PageSizeInfo* info = PageSizeInfo::getPageSizeByName(name);
  153.     if (!info)
  154.     fxFatal("Unknown page size \"%s\"", name);
  155.     pageWidth = info->width();
  156.     pageLength = info->height();
  157.     delete info;
  158. }
  159.  
  160. void
  161. faxCoverApp::open()
  162. {
  163.     if (!db)
  164.     db = new FaxDB(tildeExpand(dbName));
  165.     makeCoverSheet();
  166. }
  167.  
  168. void
  169. faxCoverApp::usage()
  170. {
  171.     fxFatal("usage: %s"
  172.     " [-t to]"
  173.     " [-c comments]"
  174.     " [-p #pages]"
  175.     " [-l to-location]"
  176.     " [-r regarding]"
  177.     " [-v to-voice-number]"
  178.     " [-x to-company]"
  179.     " [-C template-file]"
  180.     " [-s pagesize]"
  181.     " -f from"
  182.     " -n fax-number"
  183.     , (char*) appName);
  184. }
  185.  
  186. void
  187. faxCoverApp::makeCoverSheet()
  188. {
  189.     int fd;
  190.     if (cover.length() > 0 && cover[0] != '/') {
  191.     fd = ::open((char*) tildeExpand("~/" | cover), O_RDONLY);
  192.     if (fd < 0)
  193.         fd = ::open((char*) (fxStr(FAX_LIBDATA) | "/" | cover), O_RDONLY);
  194.     } else
  195.     fd = ::open((char*) cover, O_RDONLY);
  196.     if (fd < 0) {
  197.     printError( "Could not locate prototype cover sheet \"%s\"",
  198.         (char*) cover);
  199.     return;
  200.     }
  201.     printf("%%!PS-Adobe-2.0 EPSF-2.0\n");
  202.     printf("%%%%Creator: faxcover\n");
  203.     printf("%%%%Title: FlexFAX Cover Sheet\n");
  204.     time_t t = time(0);
  205.     printf("%%%%CreationDate: %s", ctime(&t));
  206.     printf("%%%%Origin: 0 0\n");
  207.     printf("%%%%BoundingBox: 0 0 %.0f %.0f\n",
  208.     (pageWidth/25.4)*72, (pageLength/25.4)*72);
  209.     printf("%%%%Pages: 1 +1\n");
  210.     printf("%%%%EndComments\n");
  211.     printf("%%%%BeginProlog\n");
  212.     printf("100 dict begin\n");
  213.     if (toName != "")
  214.     emitToDefs(toName, db->find(toName));
  215.     else
  216.     emitToDefs("<unknown>", NULL);
  217.     printf("/pageWidth %.2f def\n", pageWidth);
  218.     printf("/pageLength %.2f def\n", pageLength);
  219.     emitFromDefs(db->find(sender));
  220.     coverDef("page-count", pageCount);
  221.     emitDateDefs();
  222.     coverDef("regarding", regarding);
  223.     emitCommentDefs();
  224.     printf("%%%%EndProlog\n");
  225.     printf("%%%%Page: \"1\" 1\n");
  226.     // copy prototype cover page
  227.     char buf[16*1024];
  228.     int n;
  229.     while ((n = read(fd, buf, sizeof (buf))) > 0) 
  230.     fwrite(buf, n, 1, stdout);
  231.     ::close(fd);
  232.     printf("end\n");
  233. }
  234.  
  235. void
  236. faxCoverApp::emitToDefs(const char* to, FaxDBRecord* rec)
  237. {
  238.     if (rec) {
  239.     to = rec->find(FaxDB::nameKey);
  240.     if (toCompany == "")
  241.         toCompany = rec->find("Company");
  242.     if (toLocation == "")
  243.         toLocation = rec->find("Location");
  244.     if (toVoiceNumber == "") {
  245.         toVoiceNumber = rec->find("Voice-Number");
  246.         if (toVoiceNumber != "") {
  247.         fxStr areaCode(rec->find("Area-Code"));
  248.         if (areaCode != "")
  249.             toVoiceNumber.insert("1-" | areaCode | "-");
  250.         }
  251.     }
  252.     }
  253.     coverDef("to",        to);
  254.     coverDef("to-company",    toCompany);
  255.     coverDef("to-location",    toLocation);
  256.     coverDef("to-voice-number",    toVoiceNumber);
  257.     coverDef("to-fax-number",    toFaxNumber);
  258. }
  259.  
  260. void
  261. faxCoverApp::emitFromDefs(FaxDBRecord* rec)
  262. {
  263.     fxStr fromCompany;
  264.     fxStr fromLocation;
  265.     fxStr fromFaxNumber;
  266.     fxStr fromVoiceNumber;
  267.  
  268.     if (rec) {
  269.     fromCompany = rec->find("Company");
  270.     fromLocation = rec->find("Location");
  271.     fromFaxNumber = rec->find(FaxDB::numberKey);
  272.     fromVoiceNumber = rec->find("Voice-Number");
  273.     fxStr areaCode(rec->find("Area-Code"));
  274.     if (areaCode != "") {
  275.         if (fromFaxNumber != "")
  276.         fromFaxNumber.insert("1-" | areaCode | "-");
  277.         if (fromVoiceNumber != "")
  278.         fromVoiceNumber.insert("1-" | areaCode | "-");
  279.     }
  280.     }
  281.     coverDef("from",        sender);
  282.     coverDef("from-fax-number",    fromFaxNumber);
  283.     coverDef("from-voice-number",fromVoiceNumber);
  284.     coverDef("from-company",    fromCompany);
  285.     coverDef("from-location",    fromLocation);
  286. }
  287.  
  288. void
  289. faxCoverApp::emitCommentDefs()
  290. {
  291.     /*
  292.      * Break comment string into multiple lines (if needed).
  293.      */
  294.     coverDef("comments", comments);
  295.     int line = 1;
  296.     while (comments.length() > 0) {
  297.     // strip leading white space
  298.     while (comments.length() > 0 && isspace(comments[0]))
  299.         comments.remove(0);
  300.     int len = fxmin(comments.length(), (u_int) 35);
  301.     if (len == 35 && !isspace(comments[len-1])) {// break on word boundary
  302.         int l = len-1;
  303.         for (; l > 1 && !isspace(comments[l-1]); l--)
  304.         ;
  305.         if (l > 0)
  306.         len = l;
  307.         // otherwise, break in the middle of this really long word
  308.     }
  309.     fxStr num(line, "%u");
  310.     coverDef("comments" | num, comments.cut(0,len));
  311.     line++;
  312.     }
  313. }
  314.  
  315. void
  316. faxCoverApp::emitDateDefs()
  317. {
  318.     time_t t = time(0);
  319.     char date[128];
  320.     strftime(date, sizeof (date), "%a %b %d %Y, %H:%M %Z", localtime(&t));
  321.     coverDef("todays-date", date);
  322. }
  323.  
  324. void
  325. faxCoverApp::coverDef(const char* tag, const char* value)
  326. {
  327.     printf("/%s (", tag);
  328.     for (const char* cp = value; *cp; cp++) {
  329.     if (*cp == '(' || *cp == ')')
  330.         putchar('\\');
  331.     putchar(*cp);
  332.     }
  333.     printf(") def\n");
  334. }
  335.  
  336. fxStr
  337. faxCoverApp::tildeExpand(const fxStr& filename)
  338. {
  339.     fxStr path(filename);
  340.     if (filename.length() > 1 && filename[0] == '~') {
  341.     path.remove(0);
  342.     char* cp = getenv("HOME");
  343.     if (!cp || *cp == '\0') {
  344.         struct passwd* pwd = getpwuid(getuid());
  345.         if (!pwd)
  346.         fxFatal("Can not figure out who you are.");
  347.         cp = pwd->pw_dir;
  348.     }
  349.     path.insert(cp);
  350.     }
  351.     return (path);
  352. }
  353.  
  354. void
  355. faxCoverApp::printError(const char* va_alist ...)
  356. #define    fmt va_alist
  357. {
  358.     va_list ap;
  359.     va_start(ap, va_alist);
  360.     fprintf(stderr, "%s: ", (char*) appName);
  361.     vfprintf(stderr, fmt, ap);
  362.     va_end(ap);
  363.     fprintf(stderr, ".\n");
  364. }
  365. #undef fmt
  366.  
  367. int
  368. main(int argc, char** argv)
  369. {
  370.     faxCoverApp app;
  371.     app.initialize(argc, argv);
  372.     app.open();
  373.     return 0;
  374. }
  375.